import numpy as np
import tensorflow as tf
from tensorflow import keras
from sklearn import metrics
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Activation, Dense, Flatten, BatchNormalization, Conv2D, MaxPool2D
from tensorflow.keras.optimizers import Adam
from tensorflow.keras.metrics import categorical_crossentropy
from tensorflow.keras.preprocessing.image import ImageDataGenerator
from sklearn.metrics import confusion_matrix
import itertools
import os
import shutil
from random import randint
import random
import glob
import matplotlib.pyplot as plt
import warnings
warnings.simplefilter(action='ignore', category=FutureWarning)
%matplotlib inline
The images included in the data/skin-cancer directory are a random subset of microscopic images of Benign & Malignant Skin Cancer cells from ISIC Data-Base: https://www.isic-archive.com/#!/topWithHeader/onlyHeaderTop/gallery
# Organize data into train directories
os.chdir('C:\\Users\\רועי\\data\\skin-cancer\\benign_set')
if os.path.isdir('C:\\Users\\רועי\\data\\skin-cancer\\train\\benign') is False:
os.makedirs('C:\\Users\רועי\\data\\skin-cancer\\train\\benign')
for i in random.sample(glob.glob('*'), 500):
shutil.move(i, 'C:\\Users\\רועי\\data\\skin-cancer\\train\\benign')
os.chdir('../../')
# Organize data into train directories
os.chdir('C:\\Users\\רועי\\data\\skin-cancer\\malignant_set')
if os.path.isdir('C:\\Users\\רועי\\data\\skin-cancer\\train\\malignant') is False:
os.makedirs('C:\\Users\רועי\\data\\skin-cancer\\train\\malignant')
for i in random.sample(glob.glob('*'), 500):
shutil.move(i, 'C:\\Users\\רועי\\data\\skin-cancer\\train\\malignant')
os.chdir('../../')
# Organize data into valid directories
os.chdir('C:\\Users\\רועי\\data\\skin-cancer\\benign_set')
if os.path.isdir('C:\\Users\\רועי\\data\\skin-cancer\\valid\\benign') is False:
os.makedirs('C:\\Users\רועי\\data\\skin-cancer\\valid\\benign')
for i in random.sample(glob.glob('*'), 100):
shutil.move(i, 'C:\\Users\\רועי\\data\\skin-cancer\\valid\\benign')
os.chdir('../../')
# Organize data into valid directories
os.chdir('C:\\Users\\רועי\\data\\skin-cancer\\malignant_set')
if os.path.isdir('C:\\Users\\רועי\\data\\skin-cancer\\valid\\malignant') is False:
os.makedirs('C:\\Users\רועי\\data\\skin-cancer\\valid\\malignant')
for i in random.sample(glob.glob('*'), 100):
shutil.move(i, 'C:\\Users\\רועי\\data\\skin-cancer\\valid\\malignant')
os.chdir('../../')
train_path = 'C:\\Users\\רועי\\\data\\skin-cancer\\train'
valid_path = 'C:\\Users\\רועי\\\data\\skin-cancer\\valid'
train_batches = ImageDataGenerator(preprocessing_function=tf.keras.applications.vgg16.preprocess_input).flow_from_directory(directory=train_path, target_size=(224,224), classes=['benign','malignant'], batch_size=10)
valid_batches = ImageDataGenerator(preprocessing_function=tf.keras.applications.vgg16.preprocess_input).flow_from_directory(directory=valid_path, target_size=(224,224), classes=['benign','malignant'], batch_size=10)
assert train_batches.n == 1000
assert valid_batches.n == 200
assert train_batches.num_classes == valid_batches.num_classes == 2
# plot images in the form of a 1 by 10 grid and resize img to 20x20
def plotImages(images_arr):
fig, axes = plt.subplots(1, 10, figsize=(20,20))
axes = axes.flatten()
for img, ax in zip( images_arr, axes):
ax.imshow(img)
ax.axis('off')
plt.tight_layout()
plt.show()
train_imgs, train_labels = next(train_batches)
plotImages(train_imgs)
print(train_labels)
pysical_devices = tf.config.experimental.list_physical_devices('GPU')
print("Num GPUs Available: ", len(pysical_devices))
model = Sequential([
Conv2D(filters=32, kernel_size=(3, 3), activation='relu', padding = 'same', input_shape=(224,224,3)),
MaxPool2D(pool_size=(2, 2), strides=2),
Conv2D(filters=64, kernel_size=(3, 3), activation='relu', padding = 'same'),
MaxPool2D(pool_size=(2, 2), strides=2),
Flatten(),
Dense(units=2, activation='softmax')
])
model.summary()
model.compile(optimizer=Adam(learning_rate=0.0001), loss='categorical_crossentropy', metrics=['accuracy'])
X_train = train_batches
y_train = train_batches.classes
model.fit(x=X_train, validation_data=valid_batches, epochs=10, verbose=2)
# Organize data into test directories
os.chdir('C:\\Users\רועי\\data\\skin-cancer\\benign_set')
if os.path.isdir('C:\\Users\\רועי\\data\\skin-cancer\\test\\benign') is False:
os.makedirs('C:\\Users\רועי\\data\\skin-cancer\\test\\benign')
for i in random.sample(glob.glob('*'), 50):
shutil.move(i, 'C:\\Users\\רועי\\data\\skin-cancer\\test\\benign')
os.chdir('../../')
# Organize data into test directories
os.chdir('C:\\Users\רועי\\data\\skin-cancer\\malignant_set')
if os.path.isdir('C:\\Users\\רועי\\data\\skin-cancer\\test\\malignant') is False:
os.makedirs('C:\\Users\רועי\\data\\skin-cancer\\test\\malignant')
for i in random.sample(glob.glob('*'), 50):
shutil.move(i, 'C:\\Users\\רועי\\data\\skin-cancer\\test\\malignant')
os.chdir('../../')
test_path = 'C:\\Users\\רועי\\\data\\skin-cancer\\test'
test_batches = ImageDataGenerator(preprocessing_function=tf.keras.applications.vgg16.preprocess_input).flow_from_directory(directory=test_path, target_size=(224,224), classes=['benign','malignant'], batch_size=10, shuffle=False)
assert test_batches.n == 100
assert test_batches.num_classes == 2
test_imgs, test_labels = next(test_batches)
plotImages(test_imgs)
print(test_labels)
X_test = test_batches
y_test = test_batches.classes
predictions = model.predict(x=X_test, verbose=0)
for i in predictions:
print(i)
rounded_predictions = np.argmax(np.round(predictions), axis=-1)
for i in rounded_predictions:
print(i)
y_pred=rounded_predictions
cm = confusion_matrix(y_true=y_test, y_pred=y_pred)
def plot_confusion_matrix(cm, classes,
normalize=False,
title='Confusion matrix',
cmap=plt.cm.Blues):
"""
This function prints and plots the confusion matrix.
Normalization can be applied by setting `normalize=True`.
"""
plt.imshow(cm, interpolation='nearest', cmap=cmap)
plt.title(title)
plt.colorbar()
tick_marks = np.arange(len(classes))
plt.xticks(tick_marks, classes, rotation=45)
plt.yticks(tick_marks, classes)
if normalize:
cm = cm.astype('float') / cm.sum(axis=1)[:, np.newaxis]
print("Normalized confusion matrix")
else:
print('Confusion matrix, without normalization')
print(cm)
thresh = cm.max() / 2.
for i, j in itertools.product(range(cm.shape[0]), range(cm.shape[1])):
plt.text(j, i, cm[i, j],
horizontalalignment="center",
color="white" if cm[i, j] > thresh else "black")
plt.tight_layout()
plt.ylabel('True label')
plt.xlabel('Predicted label')
cm_plot_labels = ['benign','malignant']
plot_confusion_matrix(cm=cm, classes=cm_plot_labels, title='Confusion Matrix')
print("\033[1m The result is telling us that we have: ",(cm[0,0]+cm[1,1]),"correct predictions.")
print("\033[1m The result is telling us that we have: ",(cm[0,1]+cm[1,0]),"incorrect predictions.")
print("\033[1m We have a total predictions of: ",(cm.sum()))
from sklearn.metrics import classification_report
print(classification_report(y_test, y_pred))
#calculate Accuracy, how often is the classifier correct?
print("Accuracy of the Convolutional Neural Network model:", "{:.2%}".format(metrics.accuracy_score(y_test, y_pred)))
print("\nWell, you got a classification rate of", "{:.2%}".format(metrics.accuracy_score(y_test, y_pred)))
#calculate Precision
print("Precision of the Convolutional Neural Network model:", "{:.2%}".format(metrics.precision_score(y_test, y_pred)))
print("\nPrecision: Precision is about being precise, i.e., how precise our model is. In other words, we can say, when a model makes a prediction, how often it is correct. In our prediction case, when our Convolutional Neural Network model predicted an image is of a malignant skin cancer cell, that image is actually of a malignant skin cancer cell", "{:.2%}".format(metrics.precision_score(y_test, y_pred)) ,"of the time.")
#calculate Recall
print("Recall of the Convolutional Neural Network model:", "{:.2%}".format(metrics.recall_score(y_test, y_pred)))
print("\nRecall: If there is an image of a malignant skin cancer cell present in the test set, our Convolutional Neural Network model can identify it", "{:.2%}".format(metrics.recall_score(y_test, y_pred)) ,"of the time.")
from sklearn.metrics import roc_auc_score
from sklearn.metrics import roc_curve
cnn_roc_auc = roc_auc_score(y_test, model.predict(X_test)[:,1])
fpr, tpr, thresholds = roc_curve(y_test, model.predict_proba(X_test)[:,1])
plt.figure()
plt.plot(fpr, tpr, label='Convolutional Neural Network (area = %0.4f)' % cnn_roc_auc)
plt.plot([0, 1], [0, 1],'r--')
plt.xlim([0.0, 1.0])
plt.ylim([0.0, 1.05])
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.title('Receiver operating characteristic')
plt.legend(loc="lower right")
plt.savefig('CNN_ROC')
plt.show()
randy = randint(0,1)
if randy == 0:
os.chdir('C:\\Users\\רועי\\data\\skin-cancer\\benign_set')
if os.path.isdir('C:\\Users\\רועי\\data\\skin-cancer\\pred\\benign') is False:
os.makedirs('C:\\Users\רועי\\data\\skin-cancer\\pred\\benign')
for i in random.sample(glob.glob('*'), 1):
shutil.move(i, 'C:\\Users\\רועי\\data\\skin-cancer\\pred\\benign')
os.chdir('../../')
else:
os.chdir('C:\\Users\\רועי\\data\\skin-cancer\\malignant_set')
if os.path.isdir('C:\\Users\\רועי\\data\\skin-cancer\\pred\\malignant') is False:
os.makedirs('C:\\Users\רועי\\data\\skin-cancer\\pred\\malignant')
for i in random.sample(glob.glob('*'), 1):
shutil.move(i, 'C:\\Users\\רועי\\data\\skin-cancer\\pred\\malignant')
os.chdir('../../')
pred_path = 'C:\\Users\רועי\\data\\skin-cancer\\pred'
if randy == 0:
pred_pic1 = 'C:\\Users\רועי\\data\\skin-cancer\\pred\\benign'
else:
pred_pic1 = 'C:\\Users\רועי\\data\\skin-cancer\\pred\\malignant'
pred_batches = ImageDataGenerator(preprocessing_function=tf.keras.applications.vgg16.preprocess_input).flow_from_directory(directory=pred_path, target_size=(224,224), classes=['benign','malignant'], batch_size=10, shuffle=False)
assert pred_batches.n == 1
assert pred_batches.num_classes == 2
from IPython.display import Image
if randy == 0:
os.chdir('C:\\Users\רועי\\data\\skin-cancer\\pred\\benign')
for i in random.sample(glob.glob('*'), 1):
Image(filename=i)
else:
os.chdir('C:\\Users\רועי\\data\\skin-cancer\\pred\\malignant')
for i in random.sample(glob.glob('*'), 1):
Image(filename=i)
Image(filename=i)
if randy == 0:
print("\033[1m This is an image of a benign skin cancer cell")
else:
print("\033[1m This is an image of a malignant skin cancer cell")
accuracy = "{:.2%}".format(metrics.accuracy_score(y_test, y_pred))
pred_imgs, pred_labels = next(pred_batches)
X_pred = pred_batches
y_pred = pred_batches.classes
pred = model.predict(x=X_pred, verbose=0)
rounded_pred = np.argmax(np.round(pred), axis=-1)
if rounded_pred[0] == 0:
print("\033[1m The algorithm predict, with accuracy (i.e., confidence level) of", accuracy, "that this is an image of a benign skin cancer cell")
else:
print("\033[1m The algorithm predict, with accuracy (i.e., confidence level) of", accuracy, "that this is an image of a malignant skin cancer cell")
model.summary()
# Checks first to see if file exists already
# If not, the model is saved to disk.
import os.path
if os.path.isfile('C:\\Users\\רועי\\models\\skincancer_model.h7') is False:
model.save('C:\\Users\\רועי\\models\skincancer_model.h7')
This save functions saves:
from tensorflow.keras.models import load_model
new_model = load_model('C:\\Users\\רועי\\models\\skincancer_model.h7')
new_model.summary()
new_model.get_weights()
new_model.optimizer
if you only need to save architecture of a model, and not its weights or its training configuration, you can see the following function to save the architecture only.
# save as YAML
yaml_string = model.to_yaml()
# save as JSON
# json_string = model.to_json()
yaml_string
# model reconstruction from YAML
from tensorflow.keras.models import model_from_yaml
model_architecture = model_from_yaml(yaml_string)
# model reconstruction from JSON:
# from tensorflow.keras.models import model_from_json
# model_architecture = model_from_json(json_string)
model_architecture.summary()
If you only need to save the weights of the model, you cab use the following function save the weights only.
# Checks first to see if file exists already
# If not, the model is saved to disk.
import os.path
if os.path.isfile('C:\\Users\\רועי\\models\skincancer_model.h7') is False:
model.save_weights('C:\\Users\\רועי\\models\skincancer_model.h7')
model2 = Sequential([
Conv2D(filters=32, kernel_size=(3, 3), activation='relu', padding = 'same', input_shape=(224,224,3)),
MaxPool2D(pool_size=(2, 2), strides=2),
Conv2D(filters=64, kernel_size=(3, 3), activation='relu', padding = 'same'),
MaxPool2D(pool_size=(2, 2), strides=2),
Flatten(),
Dense(units=2, activation='softmax')
])
model2.load_weights('C:\\Users\\רועי\\models\skincancer_model.h7')
model2.get_weights()
# Delete data from train directories
os.chdir('C:\\Users\\רועי\\data\\skin-cancer\\train\\benign')
for i in random.sample(glob.glob('*'), 500):
shutil.move(i, 'C:\\Users\\רועי\\data\\skin-cancer\\benign_set')
os.chdir('../../')
os.removedirs('C:\\Users\רועי\\data\\skin-cancer\\train\\benign')
os.chdir('../../')
# Delete data from train directories
os.chdir('C:\\Users\\רועי\\data\\skin-cancer\\train\\malignant')
if os.path.isdir('C:\\Users\\רועי\\data\\skin-cancer\\malignant_set') is False:
os.makedirs('C:\\Users\רועי\\data\\skin-cancer\\malignant_set')
for i in random.sample(glob.glob('*'), 500):
shutil.move(i, 'C:\\Users\\רועי\\data\\skin-cancer\\malignant_set')
os.chdir('../../')
os.removedirs('C:\\Users\רועי\\data\\skin-cancer\\train\\malignant')
os.chdir('../../')
# Delete data from train directories
os.chdir('C:\\Users\\רועי\\data\\skin-cancer\\valid\\benign')
for i in random.sample(glob.glob('*'), 100):
shutil.move(i, 'C:\\Users\\רועי\\data\\skin-cancer\\benign_set')
os.chdir('../../')
os.removedirs('C:\\Users\רועי\\data\\skin-cancer\\valid\\benign')
os.chdir('../../')
# Delete data from valid directories
os.chdir('C:\\Users\\רועי\\data\\skin-cancer\\valid\\malignant')
if os.path.isdir('C:\\Users\\רועי\\data\\skin-cancer\\malignant_set') is False:
os.makedirs('C:\\Users\רועי\\data\\skin-cancer\\malignant_set')
for i in random.sample(glob.glob('*'), 100):
shutil.move(i, 'C:\\Users\\רועי\\data\\skin-cancer\\malignant_set')
os.chdir('../../')
os.removedirs('C:\\Users\רועי\\data\\skin-cancer\\valid\\malignant')
os.chdir('../../')
# Delete data from test directories
os.chdir('C:\\Users\\רועי\\data\\skin-cancer\\test\\benign')
for i in random.sample(glob.glob('*'), 50):
shutil.move(i, 'C:\\Users\\רועי\\data\\skin-cancer\\benign_set')
os.chdir('../../')
os.removedirs('C:\\Users\רועי\\data\\skin-cancer\\test\\benign')
os.chdir('../../')
# Delete data from test directories
os.chdir('C:\\Users\\רועי\\data\\skin-cancer\\test\\malignant')
if os.path.isdir('C:\\Users\\רועי\\data\\skin-cancer\\malignant_set') is False:
os.makedirs('C:\\Users\רועי\\data\\skin-cancer\\malignant_set')
for i in random.sample(glob.glob('*'), 50):
shutil.move(i, 'C:\\Users\\רועי\\data\\skin-cancer\\malignant_set')
os.chdir('../../')
os.removedirs('C:\\Users\רועי\\data\\skin-cancer\\test\\malignant')
os.chdir('../../')
if randy == 0:
# Delete data from pred directories
os.chdir('C:\\Users\\רועי\\data\\skin-cancer\\pred\\benign')
for i in random.sample(glob.glob('*'), 1):
shutil.move(i, 'C:\\Users\\רועי\\data\\skin-cancer\\benign_set')
os.chdir('../../')
os.removedirs('C:\\Users\רועי\\data\\skin-cancer\\pred\\benign')
else:
# Delete data from pred directories
os.chdir('C:\\Users\\רועי\\data\\skin-cancer\\pred\\malignant')
for i in random.sample(glob.glob('*'), 1):
shutil.move(i, 'C:\\Users\\רועי\\data\\skin-cancer\\malignant_set')
os.chdir('../../')
os.removedirs('C:\\Users\רועי\\data\\skin-cancer\\pred\\malignant')